﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Dotway.WPF.Controls.Utilities;

namespace Dotway.WPF.Controls
{
    [TemplatePart(Name = "PART_ColorPanel", Type = typeof(Panel))]
    public class ColorBar : Control
    {
        private ColorBarData colorHelper = new ColorBarData();
        private Panel colorPanel = null;

        public ColorBar()
        { }

        static ColorBar()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorBar), new FrameworkPropertyMetadata(typeof(ColorBar)));
        }

        public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position", typeof(double), typeof(ColorBar), new UIPropertyMetadata(0.0));
        /// <summary>
        /// This is the current position in the color panel.
        /// </summary>
        public double Position
        {
            get { return (double)GetValue(PositionProperty); }
            private set { SetValue(PositionProperty, value); }
        }

        public static readonly DependencyProperty DegreeProperty = DependencyProperty.Register("Degree", typeof(double), typeof(ColorBar), new UIPropertyMetadata(0.0));
        /// <summary>
        /// This is the degree of the H in Hsv color space. [0 - 360].
        /// </summary>
        public double Degree
        {
            get { return (double)GetValue(DegreeProperty); }
            private set { SetValue(DegreeProperty, value); }
        }
        
        public static readonly DependencyProperty HColorProperty = DependencyProperty.Register("HColor", typeof(Color), typeof(ColorBar), new UIPropertyMetadata(Color.FromRgb(255,0,0), new PropertyChangedCallback(OnHColorChanged)));
        /// <summary>
        /// This is the H color in Hsv color space.
        /// </summary>
        public Color HColor
        {
            get { return (Color)GetValue(HColorProperty); }
            set { SetValue(HColorProperty, value); }
        }

        #region OnHColorChanged

        private static void OnHColorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ColorBar control = o as ColorBar;
            if (control != null)
            {
                control.OnHColorChanged((Color)e.OldValue, (Color)e.NewValue);
            }
        }

        protected virtual void OnHColorChanged(Color oldValue, Color newValue)
        {
            SetDegree(newValue);
            SetPosition(Degree);
        }

        #endregion OnHColorChanged                 

        public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ColorBar), new UIPropertyMetadata(Orientation.Vertical, new PropertyChangedCallback(OnOrientationChanged)));
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        #region OnOrientationChanged

        private static void OnOrientationChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ColorBar control = o as ColorBar;
            if (control != null)
            {
                control.OnOrientationChanged((Orientation)e.OldValue, (Orientation)e.NewValue);
            }
        }

        protected virtual void OnOrientationChanged(Orientation oldValue, Orientation newValue)
        {
            SetBackground();
        }

        #endregion OnOrientationChanged

        public override void OnApplyTemplate()
        {
            colorPanel = this.GetTemplateChild("PART_ColorPanel") as Panel;
            if (colorPanel == null)
            {
                throw new NullReferenceException("Could not find templated part: PART_ColorPanel");
            }
            colorPanel.MouseLeftButtonUp += new MouseButtonEventHandler(OnColorPanelMouseLeftButtonUp);
            colorPanel.MouseLeftButtonDown += new MouseButtonEventHandler(OnColorPanelMouseLeftButtonDown);
            colorPanel.MouseMove += new MouseEventHandler(OnColorPanelMouseMove);
            SetBackground();

            base.OnApplyTemplate();
        }

        private void OnColorPanelMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            colorPanel.CaptureMouse();
        }

        private void OnColorPanelMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point position = e.GetPosition(colorPanel);
                UpdateColorBar(position);                
            }
        }

        private void OnColorPanelMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Point position = e.GetPosition(colorPanel);
            UpdateColorBar(position);
            Mouse.Capture(null);
        }

        private void UpdateColorBar(Point newPosition)
        {
            double relativePosition = GetRelativePosition(newPosition);              
            HColor = colorHelper.GetColor(relativePosition * 360.0);            
        }

        private void SetDegree(Color color)
        {
            Degree = colorHelper.GetDegree(color);
        }

        private void SetDegree(double relativePosition)
        {
            Degree = relativePosition * 360.0;
        }

        private void SetPosition(Point currentPosition)
        {
            if (Orientation == Orientation.Horizontal)
            {
                Position = currentPosition.X;
            }
            else
            {
                // Orientation.Vertical
                Position = currentPosition.Y;
            }
        }

        private void SetPosition(double degree)
        {
            if (colorPanel != null)
            {
                if (Orientation == Orientation.Horizontal)
                {
                    Position = (degree / 360.0) * colorPanel.ActualWidth;
                }
                else
                {
                    // Orientation.Vertical
                    Position = (degree / 360.0) * colorPanel.ActualHeight;
                }
            }
        }

        private double GetRelativePosition(Point absolutePosition)
        {
            double relativePostion = 0.0;            

            if (colorPanel != null)
            {
                if (Orientation == Orientation.Horizontal)
                {
                    relativePostion = absolutePosition.X / colorPanel.ActualWidth;                    
                }
                else
                {
                    // Orientation.Vertical
                    relativePostion = absolutePosition.Y / colorPanel.ActualHeight;
                }
            }

            relativePostion = LimitPosition(relativePostion);

            return relativePostion;
        }

        private double LimitPosition(double value)
        {
            if (value < 0)
            {
                value = 0;
            }
            else if (value > 1.0)
            {
                value = 1.0;
            }

            return value;
        }

        private void SetBackground()
        {
            if (colorPanel != null)
            {
                if (Orientation == Orientation.Horizontal)
                {
                    colorPanel.Background = colorHelper.GetHorizontalBackground();
                }
                else
                {
                    // Orientation.Vertical
                    colorPanel.Background = colorHelper.GetVerticalBackground();
                }
            }
        }
    }
}
